package com.example.child_protection.validata;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import javax.validation.*;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class BeanValidators {
    public static final String DEFAULT_SEPARATOR = "";
    public static final String ERRORMESSAGES_SEPARATOR = ", ";
    private static ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();

    public static String validateWithString( Object object, Class<?>[] groups ) throws ConstraintViolationException {
        String errorMessages = null;

        Set constraintViolations = getValidator().validate( object, groups );
        if ( !constraintViolations.isEmpty() ) {
            errorMessages = extractPropertyAndMessageAsString( constraintViolations );
        }

        return errorMessages;
    }

    public static void validateWithException( Object object, Class<?>[] groups ) throws ConstraintViolationException {
        Set constraintViolations = getValidator().validate( object, groups );
        if ( !constraintViolations.isEmpty() )
            throw new ConstraintViolationException( constraintViolations );
    }

    public static void validateWithException(Validator validator, Object object, Class<?>[] groups ) throws ConstraintViolationException {
        Set constraintViolations = validator.validate( object, groups );
        if ( !constraintViolations.isEmpty() )
            throw new ConstraintViolationException( constraintViolations );
    }

    public static List<String> extractMessage(ConstraintViolationException e ) {
        return extractMessage( e.getConstraintViolations() );
    }

    public static List<String> extractMessage( Set<? extends ConstraintViolation> constraintViolations ) {
        List errorMessages = Lists.newArrayList();
        for ( ConstraintViolation violation : constraintViolations ) {
            errorMessages.add( violation.getMessage() );
        }
        return errorMessages;
    }

    public static Map<String, String> extractPropertyAndMessage(ConstraintViolationException e ) {
        return extractPropertyAndMessage( e.getConstraintViolations() );
    }

    public static Map<String, String> extractPropertyAndMessage( Set<? extends ConstraintViolation> constraintViolations ) {
        Map errorMessages = Maps.newHashMap();
        for ( ConstraintViolation violation : constraintViolations ) {
            errorMessages.put( violation.getPropertyPath().toString(), violation.getMessage() );
        }
        return errorMessages;
    }

    public static List<String> extractPropertyAndMessageAsList( ConstraintViolationException e ) {
        return extractPropertyAndMessageAsList( e.getConstraintViolations(), "" );
    }

    public static List<String> extractPropertyAndMessageAsList( Set<? extends ConstraintViolation> constraintViolations ) {
        return extractPropertyAndMessageAsList( constraintViolations, "" );
    }

    public static List<String> extractPropertyAndMessageAsList( ConstraintViolationException e, String separator ) {
        return extractPropertyAndMessageAsList( e.getConstraintViolations(), separator );
    }

    public static List<String> extractPropertyAndMessageAsList( Set<? extends ConstraintViolation> constraintViolations,
                                                                String separator ) {
        List errorMessages = Lists.newArrayList();
        for ( ConstraintViolation violation : constraintViolations ) {
            errorMessages.add( new StringBuilder().append( violation.getPropertyPath() ).append( separator )
                    .append( violation.getMessage() ).toString() );
        }
        return errorMessages;
    }

    public static String extractPropertyAndMessageAsString( ConstraintViolationException e ) {
        return extractPropertyAndMessageAsString( e.getConstraintViolations(), "" );
    }

    public static String extractPropertyAndMessageAsString( Set<? extends ConstraintViolation> constraintViolations ) {
        return extractPropertyAndMessageAsString( constraintViolations, "" );
    }

    public static String extractPropertyAndMessageAsString( ConstraintViolationException e, String separator ) {
        return extractPropertyAndMessageAsString( e.getConstraintViolations(), separator );
    }

    public static String extractPropertyAndMessageAsString( Set<? extends ConstraintViolation> constraintViolations, String separator ) {
        StringBuilder errorMessages = new StringBuilder();

        int index = 0;
        for ( ConstraintViolation violation : constraintViolations ) {
            if ( 0 != index ) {
                errorMessages.append( ", " );
            }

            errorMessages.append( violation.getPropertyPath() ).append( separator ).append( violation.getMessage() );
            index++;
        }
        return errorMessages.toString();
    }

    public static Validator getValidator() {
        return validatorFactory.getValidator();
    }
}
